<?php

/**
 * Maikuro Framework
 *
 * LICENSE:
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * The license is bundled with this package in the file LICENSE.txt.
 * You may also obtain a copy of the License at this URL:
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @copyright  Copyright (c) 2010, Jonathan Hedrén
 * @author     Jonathan Hedrén <jonathan.hedren@gmail.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

/**
 * The Response represents an HTTP response.
 */
class Response
{
    /**
     * The body content of the response.
     *
     * @var string
     */
    private $body;

    /**
     *
     * @var array
     */
    private $exceptions = array();

    /**
     * Flag to determine whether to gzip encode the response body or not.
     *
     * @var boolean
     */
    private $gzipEncoding = false;

    /**
     * The response headers.
     *
     * @var array
     */
    private $headers = array();

    /**
     * Returns the body of the response.
     *
     * @return string
     */
    public function getBody()
    {
        return $this->body;
    }

    /**
     * Returns an array of headers.
     *
     * @return array
     */
    public function getHeaders()
    {
        return $this->headers;
    }

    /**
     * Returns an array of exceptions.
     *
     * @return array
     */
    public function getExceptions()
    {
        return $this->exceptions;
    }

    /**
     * Checks whether the response has a body or not.
     *
     * @return boolean
     */
    public function hasBody()
    {
        return ($this->body !== null);
    }

    /**
     * Sends the HTTP headers.
     *
     * @return Response
     */
    protected function sendHeaders()
    {
        foreach ($this->headers as $header => $headerValue) {
            if ($headerValue === null) {
                continue;
            }
            header($header . ': ' . $headerValue);
        }
        return $this;
    }

    /**
     * Send the full response (headers + body).
     *
     * @return Response
     */
    public function send()
    {
        if ($this->gzipEncoding
            && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) {
                $this->body = gzencode($this->body);
                $this->setHeader('Content-Encoding', 'gzip');
        }

        $content = $this->getBody();
        foreach ($this->getExceptions() as $e) {
            $content .= $e->__toString() . "\n";
        }
        $this->setHeader('Content-Length', strlen($content));

        $this->sendHeaders();
        
        echo $content;

        return $this;
    }

    /**
     * Sets the body of the response.
     *
     * @param string $content
     * @return Response
     */
    public function setBody($content)
    {
        $this->body = $content;
        return $this;
    }

    /**
     * Sets the Content-Type response header.
     *
     * @param string $contentType
     * @return Response
     */
    public function setContentType($contentType)
    {
        $this->setHeader('Content-Type', $contentType);
        return $this;
    }

    /**
     * Adds an exception.
     * 
     * @param Exception $e
     * @return Response
     */
    public function setException(Exception $e)
    {
        $this->exceptions[] = $e;
        return $this;
    }

    /**
     * Sets a HTTP header.
     *
     * @param string $header
     * @return Response
     */
    public function setHeader($header, $headerValue)
    {
        $this->headers[$header] = $headerValue;
        return $this;
    }

    /**
     * Sets the HTTP status.
     *
     * @param string $httpStatus
     * @param integer $responseCode
     * @return Response
     */
    public function setHttpStatus($httpStatus, $responseCode)
    {
        header($httpStatus, true, $responseCode);
        $this->setHeader('Status', $responseCode);
        return $this;
    }

    /**
     * Sets whether to gzip encode the response body or not.
     *
     * @param boolean $gzipEncoding
     * @return Response
     */
    public function useGzipEncoding($gzipEncoding)
    {
        $this->gzipEncoding = $gzipEncoding;
        return $this;
    }
}